package top.huhuiyu.ds;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

/**
 * java内置结构数据演示
 * 
 * @author Aiden Pearce
 *
 */
public class DsDemo {
  // 生成随机数
  private static Random random = new Random();

  /*
   * 生成演示用的数据集合
   */
  public static List<DsEntity> makeData() {
    List<DsEntity> list = new ArrayList<>();
    list.add(new DsEntity(100, "张5"));
    list.add(new DsEntity(101, "张9"));
    list.add(new DsEntity(102, "张2"));
    list.add(new DsEntity(103, "张55"));
    list.add(new DsEntity(104, "张14"));
    list.add(new DsEntity(105, "张52"));
    list.add(new DsEntity(106, "张54"));
    list.add(new DsEntity(107, "强无敌"));
    list.add(new DsEntity(108, "张8777"));
    list.add(new DsEntity(109, "张6666"));

    return list;
  }

  /*
   * 从list中随机挑选一个数据
   * 
   * @param list
   * 
   * @return 随机挑选的数据
   */
  public static DsEntity rand(List<DsEntity> list) {
    if (list == null || list.isEmpty()) {
      throw new RuntimeException("集合为空");
    }
    // (上界—下界+1)+下界
    int index = random.nextInt(list.size());
    return list.get(index);
  }

  /**
   * 从list中随机挑选count数量的随机数据
   * 
   * @param list
   *          挑选数据的集合
   * @param count
   *          随机数据的数量
   * @return 随机数集合
   */
  public static List<DsEntity> rand(List<DsEntity> list, int count) {
    List<DsEntity> result = new ArrayList<>();
    if (list == null || list.isEmpty()) {
      return result;
    }
    for (int i = 0; i < count; i++) {
      int index = random.nextInt(list.size());
      result.add(list.get(index));
    }
    return result;
  }

  /**
   * 在list中随机挑选count数量的数据，不允许重复的值，count值不能超过list的数量
   * 
   * @param list
   * @param count
   * @return
   */
  public static List<DsEntity> choice(List<DsEntity> list, int count) {
    List<DsEntity> rist = new ArrayList<>();
    if (list == null || list.isEmpty()) {
      return rist;
    }
    // while循环，长度大于随机数量
    while (rist.size() < count) {
      // 取随机数
      int index = random.nextInt(list.size());
      DsEntity ds = list.get(index);
      boolean find = false;
      for (DsEntity dsEntity : rist) {
        if (ds.equals(dsEntity)) {
          find = true;
          break;
        }
      }
      if (!find) {
        rist.add(ds);
      }
      return rist;
    }

    return rist;
  }

  /**
   * 读取文本文件内容，统计出出现了多少个不同的字符（不包括空白字符）返回为字符串
   * 
   * @param textFile
   *          文本文件路径
   * @param sort
   *          是否排序,false就按照出现的次序排序，true就按照字符排序规则排序
   * @return 出现的字符构成的字符串
   * @throws Exception
   */
  public static String countText(String textFile, boolean sort) throws Exception {
    // 读取文本的最佳对象
    Scanner scanner = new Scanner(new File(textFile), "UTF-8");
    // 可变字符串，当字符串拼接过多的时候应该使用该对象，否则可能造成内存溢出
    StringBuilder sb = new StringBuilder();
    // 以行为单位读取字符流.hasNextLine判断是否还有一行数据
    while (scanner.hasNextLine()) {
      // nextLine读取一行字符串
      sb.append(scanner.nextLine());
    }
    // 将可变字符串转换为字符串对象
    String content = sb.toString();
    scanner.close();
    // 正则替换所有空白字符
    content = content.replaceAll("\\s", "");
    // System.out.println(content);
    // 去掉重复字符(set集合不可以添加重复的数据，相同的只会添加一次)
    // HashSet是默认的实现
    // TreeSet会自动排序，LinkedHashSet会记住添加的次序
    Set<Character> set = sort ? new TreeSet<>() : new LinkedHashSet<>(); // new HashSet<>();
    // 分割成字符的数组
    char[] chars = content.toCharArray();
    for (char c : chars) {
      set.add(c);
    }
    // 将set中的数据连接成String
    sb = new StringBuilder();
    for (char c : set) {
      sb.append(c);
    }

    return sb.toString();
  }

  /**
   * 统计文本文件中出现的字符，以及对应的数量（不包括空白字符）
   * 
   * @param textFile
   * @param sort
   * @return
   * @throws Exception
   */
  public static Map<Character, Integer> countTextNumber(String textFile, boolean sort) throws Exception {
    // Map数据结构是键值对，放入数据是一对，通过key可以找到对应的值
    Map<Character, Integer> map = new HashMap<>();
    // 读取文件到String
    Scanner scanner = new Scanner(new File(textFile));
    StringBuilder sb = new StringBuilder();
    while (scanner.hasNextLine()) {
      sb.append(scanner.nextLine());
    }
    scanner.close();
    String content = sb.toString().replaceAll("\\s", "");
    // 统计并计数
    char[] chars = content.toCharArray();
    
    
    
    
    for (char c : chars) {
      // 如果map没有C对应的数据，那么就将C和数量1为一组添加到map中
      // containsKey就是判断C是否在map的key中存在
      if (!map.containsKey(c)) {
        map.put(c, 1);
      } else {
        // 如果map中存在对应的数据，就将数量取回来加1，再放回去
        int count = map.get(c) + 1;
        map.put(c, count);
      }
    }

    return map;
  }

  public static void main(String[] args) {

    try {
      Map<Character, Integer> map = countTextNumber("demo.txt", false);
      // map是循环是检值对一组
      for (Map.Entry<Character, Integer> kv : map.entrySet()) {
        System.out.println(kv.getKey() + "==>" + kv.getValue());

      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    // List<DsEntity> list = makeData();
    // System.out.println(rand(list));
    // System.out.println(rand(list));
    // System.out.println("==========");
    // List<DsEntity> randList = rand(list, 3);
    // // foreach循环（一次获取一笔仅向前的迭代）
    // // for(集合或数组中的数据类型，每次循环得到变量值：集合或者数组)
    // for (DsEntity dsEntity : randList) {
    // System.out.println(dsEntity);
    // }
    // System.out.println("=============");
    // try {
    // System.out.println(countText("demo.txt", false));
    // System.out.println(countText("demo.txt", true));
    // } catch (Exception e) {
    // e.printStackTrace();
    // }
    // System.out.println("====================================");
    // long start = System.currentTimeMillis();// 当前时间戳
    // Random r = new Random();
    // Set<Integer> sets = new TreeSet<>();
    // for (int i = 0; i < 100000; i++) {
    // sets.add(r.nextInt(100000));
    // }
    // System.out.println(sets.size());
    // System.out.println("时间消耗" + (System.currentTimeMillis() - start));

  }

}
//map.put(key.value):添加键值对数据
//value=map.get(key):获取key对应的数据
//map.containsKey(key):检查key是否存在
//map.entrySet:获取map的值，结构是Map.Entry
//     Map.Entry.getKey 获取key,Map,Entry.getValue获取值
//map.keySet :获取键的set集合
//map.values:获取值的集合(很少使用，因为值可以通过key获取到)



//set 不允许重复值，map是键值对，list快速随机下标访问，记住添加次序
//Stack先进后出  Queue先进先出
//基础值类型 byte int long float double boolean char string 
